Skip to content

feat: AI commit-message sub-agent with live streaming + commit bar controls#38

Merged
BotCoder254 merged 1 commit into
mainfrom
feat/ai-commit-message-subagent
Jul 4, 2026
Merged

feat: AI commit-message sub-agent with live streaming + commit bar controls#38
BotCoder254 merged 1 commit into
mainfrom
feat/ai-commit-message-subagent

Conversation

@BotCoder254

@BotCoder254 BotCoder254 commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

Deepens the git integration with a commit-message sub-agent driven by the same Claude Agent SDK that powers the main agent, plus a redesigned commit bar — all inside the existing UI/theme and hardened per the repo's security contract.

Git sub-agent (isolated one-shot, streams live)

  • GitManager.buildCommitContext() assembles everything main-side: staged diff (capped 60 KB), binary-flagged file list, recent commit subjects for style inference — argv-only git, credentials redacted.
  • AgentManager.generateCommitMessage() runs a single-turn, tool-less SDK query (pinned Haiku model, allowedTools: [] and deny-all canUseTool, no resume, no transcript, no MCP servers, no lifecycle changes). Deltas stream over a new dedicated git:commit-message-stream event straight into the commit textarea; cancelable per workspace.
  • The sub-agent only proposes — the user's Commit button remains the sole executor.

Commit bar (same design language)

  • Narrow Commit N button + bordered Stage all / Unstage all buttons + Generate ⇄ Cancel in one control row; textarea goes read-only while streaming; Cmd/Ctrl+Enter unchanged.
  • Draft moved into useGitStore (survives tab switches); failed/canceled runs restore the pre-generation draft; workspace switches cancel in-flight runs.

Security hardening

  • New channels go through the sender-validated handle() wrapper; only renderer input is a workspace id (assertId).
  • Size caps in GIT_LIMITS.commitGen; prompt double-checked against AGENT_LIMITS.promptMax; errors/stderr redacted.

Test plan

  • npx vite build --config vite.renderer.config.mts passes
  • npm run lint clean
  • npm start boots with all Forge targets built, IPC registered, no errors
  • Diff audit: no dark:, no gradients, no off-palette hex, no shell: true
  • Manual: stage files → Generate streams live → edit → Commit commits the edited text

🤖 Generated with Claude Code


Note

Medium Risk
New agent IPC path sends staged diffs to the model (credentials redacted, tools disabled, no auto-commit), but it expands sensitive code exposure to the LLM and adds concurrent SDK usage beside chat runs.

Overview
Adds AI-assisted commit messages in the Git panel: the renderer only sends a workspace id; the main process builds capped, redacted context from staged changes and runs an isolated, tool-less Claude SDK one-shot that proposes text only (Commit still goes through git commit).

Main process: GitManager.buildCommitContext() gathers staged diff, file list, and recent subjects under GIT_LIMITS.commitGen. AgentManager.generateCommitMessage() uses a pinned Haiku model, streams deltas on git:commit-message-stream, and supports per-workspace cancel without touching session agent lifecycle. New IPC generate/cancel handlers wire GitManager + AgentManager.

Renderer: Commit draft lives in useGitStore with live streaming into the textarea; Generate/Cancel, Stage all/Unstage all, and read-only-while-generating behavior in GitPanel. Failed or canceled runs restore the pre-generation draft; workspace switches cancel in-flight generation.

Reviewed by Cursor Bugbot for commit 9546559. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Added AI-assisted commit message generation with live streaming and cancel support in the Git workflow.
    • The commit editor now shows generation progress, supports cancel/generate actions, and prevents committing while a message is being generated.
    • The app now uses staged changes and recent commit history to draft commit messages.
  • Bug Fixes

    • Improved handling for non-repo states and empty staged changes, with clearer failure responses and safer UI reset behavior.

…ntrols

Add an isolated, tool-less one-shot Claude Agent SDK run that proposes
commit messages from the staged diff and streams them live into the git
panel over a dedicated git:commit-message-stream IPC event — never
through the conversation store or agent lifecycle.

- GitManager.buildCommitContext: main-side staged diff (60 KB cap),
  binary-flagged file list, recent subjects for style inference, all
  argv-only git with credential redaction
- AgentManager.generateCommitMessage: pinned Haiku model, maxTurns 1,
  allowedTools [] + deny-all canUseTool, no resume/transcript/MCP,
  cancelable per workspace and hooked into cleanup()
- Commit bar: narrow Commit button plus Stage all / Unstage all and a
  Generate/Cancel control in one row, same tokens and design language
- useGitStore: draft lives in the store, streams append live, failed or
  canceled runs restore the user's pre-generation draft
- Hardened IPC: sender-validated handle(), assertId-only renderer input,
  GIT_LIMITS.commitGen caps, redacted errors/logs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@amazon-q-developer amazon-q-developer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR successfully implements AI-powered commit message generation using the Claude agent. The implementation follows secure coding practices with proper input validation, error handling, and resource cleanup. The feature integrates cleanly with the existing architecture and doesn't introduce any security vulnerabilities or functional defects.

Key strengths:

  • Secure execution with proper input validation and size caps
  • Well-structured error handling with classification and recovery
  • Clean separation between commit generation and the main agent workflow
  • Proper cancellation and cleanup mechanisms
  • Follows established patterns for SDK integration and IPC communication

No blocking issues found. The code is ready to merge.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds an AI-powered Git commit message generation feature. It introduces shared types and IPC channels for commit-message streaming, a GitManager.buildCommitContext method to gather staged-change context, an AgentManager sub-agent to generate/cancel messages, and renderer store/UI wiring in useGitStore and GitPanel.

Changes

AI Commit Message Generation

Layer / File(s) Summary
Shared types, constants, and IPC channels
src/shared/types.ts, src/shared/constants.ts, src/shared/ipc-channels.ts
Adds GitCommitContext, GitCommitMessageStreamEvent, GenerateCommitMessageResult types, GIT_LIMITS.commitGen caps, and new generate/cancel/stream IPC channel constants.
GitManager commit context builder
src/main/managers/GitManager.ts
Adds buildCommitContext to gather staged file metadata, capped/redacted diff, and recent commit subjects; exports redactRemote.
AgentManager commit-message sub-agent
src/main/managers/AgentManager.ts
Implements generateCommitMessage/cancelCommitMessage with a pinned model, tool-less single-turn run, streaming deltas, prompt-building, and message polishing helpers; tracks per-workspace runs and cancels them on shutdown.
IPC wiring and preload bridge
src/main/ipc/gitHandlers.ts, src/main/ipc/index.ts, src/preload/index.ts
Registers new IPC handlers for generate/cancel, updates registerGitHandlers to accept AgentManager, and exposes generateCommitMessage, cancelCommitMessage, onCommitMessageStream on the preload git API.
Renderer store and Changes UI
src/renderer/stores/useGitStore.ts, src/renderer/features/git/GitPanel.tsx
Adds commitMessage/generatingMessage state and actions with stream-event handling and draft restoration; updates ChangesView with Generate/Cancel controls and generation-aware commit gating.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitPanel
  participant useGitStore
  participant Preload
  participant gitHandlers
  participant GitManager
  participant AgentManager

  GitPanel->>useGitStore: generateCommitMessage()
  useGitStore->>Preload: api.generateCommitMessage(workspaceId)
  Preload->>gitHandlers: invoke gitCommitMessageGenerate
  gitHandlers->>GitManager: buildCommitContext(workspaceId)
  GitManager-->>gitHandlers: GitCommitContext
  gitHandlers->>AgentManager: generateCommitMessage(wsId, ctx)
  AgentManager-->>Preload: gitCommitMessageStream (delta events)
  Preload-->>useGitStore: onCommitMessageStream delta
  AgentManager-->>gitHandlers: GenerateCommitMessageResult
  gitHandlers-->>Preload: result
  Preload-->>useGitStore: done
  useGitStore-->>GitPanel: commitMessage updated
Loading
sequenceDiagram
  participant GitPanel
  participant useGitStore
  participant Preload
  participant AgentManager

  GitPanel->>useGitStore: cancelCommitMessage()
  useGitStore->>Preload: api.cancelCommitMessage(workspaceId)
  Preload->>AgentManager: invoke gitCommitMessageCancel
  AgentManager-->>Preload: gitCommitMessageStream (canceled)
  Preload-->>useGitStore: onCommitMessageStream canceled
  useGitStore-->>GitPanel: draft restored, generatingMessage=false
Loading

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: an AI commit-message sub-agent with streaming and commit UI controls.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ai-commit-message-subagent

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@BotCoder254 BotCoder254 merged commit 583809a into main Jul 4, 2026
3 of 11 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/managers/AgentManager.ts`:
- Around line 962-967: Cap the non-diff sections of the commit prompt in
buildCommitPrompt() so staged paths and recent subjects cannot push the prompt
over AGENT_LIMITS.promptMax. Update the prompt assembly in AgentManager to
truncate or limit the 200 staged paths and 20 recent subjects before
concatenation, and keep the existing prompt.length guard as a final safety
check. Locate the change in buildCommitPrompt() and the commit prompt generation
path used by commitGen so the full prompt stays bounded even when the diff is
already within commitGen.diffCharsMax.

In `@src/main/managers/GitManager.ts`:
- Around line 296-301: The staged-file list is being silently truncated by the
`.slice(0, caps.filesMax)` in GitManager’s commit context assembly, so add a
`filesTruncated` flag to `GitCommitContext` and set it when staged files exceed
the cap. Update the context-building logic that returns from
`status(...)`/commit prompt preparation to carry this boolean alongside
`diffTruncated`, and adjust `buildCommitPrompt` to explicitly mention when
staged files were omitted so the `Staged files (...)` header does not
under-report without warning.
- Around line 313-318: The diff handling in GitManager’s cached diff flow is
redacting too late, so partial credentials can survive truncation. Update the
logic around runGit, rawDiff, and redactRemote so the full raw diff is passed
through redactRemote first, and only then slice the redacted result to
caps.diffCharsMax if needed. Keep the existing diffTruncated behavior, but make
sure the final diff assigned for the sub-agent prompt always comes from the
redacted text, not the pre-redaction slice.

In `@src/renderer/features/git/GitPanel.tsx`:
- Around line 319-322: The commit message template seeding in GitPanel is only
triggered by changes to template, so it won’t run again when the active
workspace changes and commitMessage is reset. Update the useEffect in GitPanel
to also depend on the active workspace state (or move the template seeding into
the workspace reset handler) so the draft is reinitialized for each newly active
workspace; use the existing useGitStore state access and setCommitMessage logic
to locate the change.

In `@src/renderer/stores/useGitStore.ts`:
- Around line 89-96: The generation lifecycle in useGitStore is using the
current active workspace instead of the workspace that started the run, so
cancellation and stream filtering can hit the wrong commit message. Update the
generation-scoped tracking in useGitStore to remember the originating workspace
id when the run begins, then use that stored id in workspace.onChanged,
cancelCommitMessage(), and any delta/response filtering so only the in-flight
workspace is canceled or updated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fbf17dc2-ed7c-4d15-859a-e63a5ba3c277

📥 Commits

Reviewing files that changed from the base of the PR and between 6e9eae7 and 9546559.

📒 Files selected for processing (10)
  • src/main/ipc/gitHandlers.ts
  • src/main/ipc/index.ts
  • src/main/managers/AgentManager.ts
  • src/main/managers/GitManager.ts
  • src/preload/index.ts
  • src/renderer/features/git/GitPanel.tsx
  • src/renderer/stores/useGitStore.ts
  • src/shared/constants.ts
  • src/shared/ipc-channels.ts
  • src/shared/types.ts

Comment on lines +962 to +967
try {
const prompt = buildCommitPrompt(ctx);
if (prompt.length > AGENT_LIMITS.promptMax) {
// Belt + braces: GitManager's commitGen caps keep us far below this.
throw new Error('Commit context too large.');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n 'promptMax' src/shared/constants.ts

Repository: BotCoder254/limboo

Length of output: 181


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== constants ==\n'
sed -n '1,120p' src/shared/constants.ts

printf '\n== AgentManager around buildCommitPrompt call ==\n'
sed -n '930,995p' src/main/managers/AgentManager.ts

printf '\n== buildCommitPrompt definition/usages ==\n'
rg -n "function buildCommitPrompt|const buildCommitPrompt|buildCommitPrompt\(" src/main src/shared -n -A40 -B20

printf '\n== GIT_LIMITS commitGen ==\n'
rg -n "commitGen|diffCharsMax" src -n -A20 -B10

Repository: BotCoder254/limboo

Length of output: 43871


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== GitManager buildCommitContext around file/subject shaping ==\n'
sed -n '292,380p' src/main/managers/GitManager.ts

printf '\n== any truncation/redaction helpers used there ==\n'
rg -n "redactRemote|sanitize|truncate|branch" src/main/managers/GitManager.ts -n -A8 -B8

printf '\n== Git status shape and branch source ==\n'
rg -n "interface GitStatus|type GitStatus|branch:" src/shared src/main -n -A20 -B10

Repository: BotCoder254/limboo

Length of output: 50374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== GitFileChange / status parsing ==\n'
rg -n "interface GitFileChange|parseStatus\\(|files:" src/shared src/main -n -A30 -B10

printf '\n== any explicit path-length caps in git status/context flow ==\n'
rg -n "pathMax|file.*Max|status.*Max|commitGen|filesMax|branchMax|refNameMax" src/main src/shared -n -A4 -B4

Repository: BotCoder254/limboo

Length of output: 50374


Cap the non-diff parts of the commit prompt. buildCommitPrompt() still includes up to 200 staged paths and 20 recent subjects, and those strings aren’t length-capped here. A large repo can still push the prompt past promptMax even when the diff stays within commitGen.diffCharsMax.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/managers/AgentManager.ts` around lines 962 - 967, Cap the non-diff
sections of the commit prompt in buildCommitPrompt() so staged paths and recent
subjects cannot push the prompt over AGENT_LIMITS.promptMax. Update the prompt
assembly in AgentManager to truncate or limit the 200 staged paths and 20 recent
subjects before concatenation, and keep the existing prompt.length guard as a
final safety check. Locate the change in buildCommitPrompt() and the commit
prompt generation path used by commitGen so the full prompt stays bounded even
when the diff is already within commitGen.diffCharsMax.

Comment on lines +296 to +301

const status = await this.status(workspaceId);
const stagedFiles = status.files.filter((f) => f.staged).slice(0, caps.filesMax);
if (stagedFiles.length === 0) {
return { root, branch: status.branch, files: [], diff: '', diffTruncated: false, recentSubjects: [] };
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Staged-file list is silently capped with no truncation signal.

Files beyond caps.filesMax are dropped via .slice(), but unlike the diff (diffTruncated), there's no equivalent flag — so buildCommitPrompt's Staged files (${ctx.files.length}) header can under-report the true count without any indication to the model (or user) that entries were omitted.

Consider adding a filesTruncated boolean to GitCommitContext mirroring diffTruncated, so the prompt can note it explicitly on very large commits.

Also applies to: 334-347

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/managers/GitManager.ts` around lines 296 - 301, The staged-file list
is being silently truncated by the `.slice(0, caps.filesMax)` in GitManager’s
commit context assembly, so add a `filesTruncated` flag to `GitCommitContext`
and set it when staged files exceed the cap. Update the context-building logic
that returns from `status(...)`/commit prompt preparation to carry this boolean
alongside `diffTruncated`, and adjust `buildCommitPrompt` to explicitly mention
when staged files were omitted so the `Staged files (...)` header does not
under-report without warning.

Comment on lines +313 to +318
const diffRes = await runGit(root, ['diff', '--cached', '--no-color', '--no-ext-diff'], {
maxBuffer: GIT_LIMITS.diffBytesMax + 1024,
});
const rawDiff = diffRes.stdout;
const diffTruncated = rawDiff.length > caps.diffCharsMax;
const diff = redactRemote(diffTruncated ? rawDiff.slice(0, caps.diffCharsMax) : rawDiff);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Redact before truncating, not after.

redactRemote is applied to the diff after it's sliced to diffCharsMax. If the cut lands mid-credential (e.g. https://<token>@host/... truncated right before the @), the redaction regex — which requires the trailing @ to match — won't catch the partial token, and it flows into the sub-agent prompt un-redacted.

🔒 Proposed fix: redact the full diff, then truncate
     const rawDiff = diffRes.stdout;
-    const diffTruncated = rawDiff.length > caps.diffCharsMax;
-    const diff = redactRemote(diffTruncated ? rawDiff.slice(0, caps.diffCharsMax) : rawDiff);
+    const redactedDiff = redactRemote(rawDiff);
+    const diffTruncated = redactedDiff.length > caps.diffCharsMax;
+    const diff = diffTruncated ? redactedDiff.slice(0, caps.diffCharsMax) : redactedDiff;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const diffRes = await runGit(root, ['diff', '--cached', '--no-color', '--no-ext-diff'], {
maxBuffer: GIT_LIMITS.diffBytesMax + 1024,
});
const rawDiff = diffRes.stdout;
const diffTruncated = rawDiff.length > caps.diffCharsMax;
const diff = redactRemote(diffTruncated ? rawDiff.slice(0, caps.diffCharsMax) : rawDiff);
const diffRes = await runGit(root, ['diff', '--cached', '--no-color', '--no-ext-diff'], {
maxBuffer: GIT_LIMITS.diffBytesMax + 1024,
});
const rawDiff = diffRes.stdout;
const redactedDiff = redactRemote(rawDiff);
const diffTruncated = redactedDiff.length > caps.diffCharsMax;
const diff = diffTruncated ? redactedDiff.slice(0, caps.diffCharsMax) : redactedDiff;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/managers/GitManager.ts` around lines 313 - 318, The diff handling in
GitManager’s cached diff flow is redacting too late, so partial credentials can
survive truncation. Update the logic around runGit, rawDiff, and redactRemote so
the full raw diff is passed through redactRemote first, and only then slice the
redacted result to caps.diffCharsMax if needed. Keep the existing diffTruncated
behavior, but make sure the final diff assigned for the sub-agent prompt always
comes from the redacted text, not the pre-redaction slice.

Comment on lines 319 to 322
useEffect(() => {
setMessage((m) => (m === '' && template ? template : m));
const { commitMessage, setCommitMessage } = useGitStore.getState();
if (commitMessage === '' && template) setCommitMessage(template);
}, [template]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file first, then inspect the specific sections.
ast-grep outline src/renderer/features/git/GitPanel.tsx --view expanded || true
ast-grep outline src/renderer/stores/useGitStore.ts --view expanded || true

echo '--- GitPanel.tsx (around the effect) ---'
sed -n '300,335p' src/renderer/features/git/GitPanel.tsx

echo '--- useGitStore.ts (workspace switch / hydrate path) ---'
rg -n "workspace\.onChanged|commitMessage|commitMessageTemplate|setCommitMessage|hydrate|status" src/renderer/stores/useGitStore.ts src/renderer -n -A 3 -B 3

Repository: BotCoder254/limboo

Length of output: 50375


Template isn't reapplied after workspace switches. commitMessage is cleared in the workspace-change handler, but this effect only depends on template, so the draft won’t be seeded again for a newly active workspace unless the setting changes. Key it to the active workspace, or seed the template during the workspace reset.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/features/git/GitPanel.tsx` around lines 319 - 322, The commit
message template seeding in GitPanel is only triggered by changes to template,
so it won’t run again when the active workspace changes and commitMessage is
reset. Update the useEffect in GitPanel to also depend on the active workspace
state (or move the template seeding into the workspace reset handler) so the
draft is reinitialized for each newly active workspace; use the existing
useGitStore state access and setCommitMessage logic to locate the change.

Comment on lines +89 to +96
/**
* Generation-scoped bookkeeping (module-local, not store state): the user's
* pre-generation draft — restored when a run errors/cancels before any text
* arrived — and whether the in-flight run produced at least one delta.
*/
let draftBackup = '';
let sawDelta = false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the relevant store and related workspace/generation code.
git ls-files | rg 'src/renderer/stores/useGitStore\.ts|src/.*workspace|src/.*git|src/main/.*agent|src/.*/gitApi|src/.*/AgentManager'

echo '--- useGitStore.ts outline ---'
ast-grep outline src/renderer/stores/useGitStore.ts --view expanded

echo '--- relevant symbols / calls in useGitStore.ts ---'
rg -n "generatingMessage|commitMessage|draftBackup|sawDelta|cancelCommitMessage|generateCommitMessage|workspace\.onChanged|activeWs\(" src/renderer/stores/useGitStore.ts

echo '--- surrounding lines around workspace.onChanged and cancel/generate ---'
sed -n '120,230p' src/renderer/stores/useGitStore.ts

echo '--- workspace active id helper and change event definitions ---'
rg -n "function activeWs|const activeWs|activeWs\(|workspace\.onChanged|onChanged\(" src/renderer -g '!**/dist/**' -g '!**/build/**'

echo '--- gitApi / cancellation endpoint wiring ---'
rg -n "cancelCommitMessage|generateCommitMessage" src -g '!**/dist/**' -g '!**/build/**'

echo '--- agent-side commit generation bookkeeping ---'
rg -n "commitGenRuns|cancelCommitMessage|generateCommitMessage|workspaceId" src/main src -g '!**/dist/**' -g '!**/build/**'

Repository: BotCoder254/limboo

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- useGitStore.ts focused snippet ---'
sed -n '74,215p' src/renderer/stores/useGitStore.ts

echo '--- useWorkspaceStore.ts focused snippet ---'
sed -n '1,140p' src/renderer/stores/useWorkspaceStore.ts

echo '--- AgentManager commit generation / cancel logic ---'
sed -n '911,1065p' src/main/managers/AgentManager.ts

echo '--- git IPC handlers for commit generation ---'
sed -n '100,130p' src/main/ipc/gitHandlers.ts

Repository: BotCoder254/limboo

Length of output: 17230


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- who hydrates workspace/git stores ---'
rg -n "useWorkspaceStore\.getState\(\)\.hydrate|useGitStore\.getState\(\)\.hydrate|hydrate\(\)" src/renderer -g '!**/dist/**' -g '!**/build/**'

echo '--- workspace event contract in preload/shared/main ---'
rg -n "onChanged\(" src/preload src/main src/shared -g '!**/dist/**' -g '!**/build/**'

echo '--- workspace manager changed event emission ---'
rg -n "broadcast.*workspace|onChanged|WorkspaceChanged|activeId" src/main/managers src/main/ipc src/preload -g '!**/dist/**' -g '!**/build/**'

Repository: BotCoder254/limboo

Length of output: 1508


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- workspace event types and bridge wiring ---'
sed -n '1,220p' src/shared/types.ts
echo '--- preload workspace bridge ---'
sed -n '1,260p' src/preload/index.ts
echo '--- main workspace manager active-change emission ---'
rg -n "onChanged|changed|setActive|activeId|broadcast" src/main/managers/workspace src/main/ipc/workspaceHandlers.ts src/main/index.ts -g '!**/dist/**' -g '!**/build/**'

Repository: BotCoder254/limboo

Length of output: 21920


Track the generating workspace, not activeWs()

workspace.onChanged runs after activeId has already switched, so cancelCommitMessage() targets the new workspace instead of the in-flight run. That leaves the old generation running and lets its later stream frames mutate commitMessage if the user switches back. Keep the originating workspace id with the run and use it for cancel/filtering.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/stores/useGitStore.ts` around lines 89 - 96, The generation
lifecycle in useGitStore is using the current active workspace instead of the
workspace that started the run, so cancellation and stream filtering can hit the
wrong commit message. Update the generation-scoped tracking in useGitStore to
remember the originating workspace id when the run begins, then use that stored
id in workspace.onChanged, cancelCommitMessage(), and any delta/response
filtering so only the in-flight workspace is canceled or updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant